home *** CD-ROM | disk | FTP | other *** search
- /* OS- and machine-dependent stuff for IBM-PC running MS-DOS */
-
- #include <stdio.h>
- #include <ctype.h>
-
- #if (defined(MSC) || defined(__TURBOC__))
- # include <process.h>
- # include <signal.h>
- # ifdef MSC
- # include <malloc.h>
- void (*getvect())();
- # endif
- #else
- # ifdef RAWCON
- # include <sgtty.h>
- # endif
- #endif
-
- #include "global.h"
- #include "config.h"
- #include "mbuf.h"
- #include "internet.h"
- #include "iface.h"
- #include "cmdparse.h"
- #include "timer.h"
- #include "environ.h"
-
- /* Interface list header */
- struct interface *ifaces;
-
- #if (!defined(MSC) && !defined(__TURBOC__))
- /* Aztec memory allocation control */
- int _STKLOW = 0; /* Stack above heap */
- int _STKSIZ = 4096/16; /* 4K stack -- overridden in grabcore */
- int _HEAPSIZ = 4096/16; /* Isn't really used */
- int _STKRED = 4096; /* Stack red zone in bytes -- this really matters */
- #endif
-
- char ttbuf[BUFSIZ];
-
- #ifdef SERVERS
- extern FILE *logfp; /* log file pointer */
- extern char logname[]; /* log file name */
- #endif
-
- #ifdef TRACE
- extern FILE *trfp; /* trace file pointer */
- extern char trname[]; /* trace file name */
- #endif
-
- static unsigned watchhw; /* watchdog hardware reset value */
- static unsigned watchport; /* watchdog output port number */
-
- #if (defined(MSC) || defined(__TURBOC__))
- /* critical error handler stuff - will fail system calls all the time */
-
- void (*orgcritvect)(void);
- extern void crit_hdl(void);
-
- void crit_remove (void)
-
- {
- setvect(0x24,orgcritvect);
- }
- #endif
-
- /* Called at startup time to set up console I/O, memory heap */
- ioinit()
- {
- #if (!defined(MSC) && !defined(__TURBOC__))
- # ifdef RAWCON
- struct sgttyb ttybuf;
- # endif
- #endif
-
- /* Save these file table entries for something more useful */
- /* PE1CHL: this seems to cause problems so let's skip it for awhile */
- #ifdef CLOSEDEVS
- # ifdef stdaux
- fclose(stdaux);
- # endif
- # ifdef stdprn
- fclose(stdprn);
- # endif
- # ifdef stdprt
- fclose(stdprt);
- # endif
- #endif
-
- #if (!defined(MSC))
- /* Interrupts use a special stack deep in data space.
- * Calls to sbrk() (invoked by malloc when it needs more memory
- * from the system) at interrupt time will fail because sbrk()
- * will think that the stack has overwritten the heap. So
- * grab all the memory we can now for the heap so that malloc
- * won't have to call sbrk and alloc_mbuf() won't fail unnecessarily
- * at interrupt time.
- */
- grabcore();
- #endif
-
- setbuf(stdout,ttbuf);
-
- #if (defined(MSC) || defined(__TURBOC__))
- signal(SIGINT,SIG_IGN); /* don't like killing NET */
- #else
- # ifdef RAWCON
- /* Put display in raw mode. Note that this breaks tab expansion,
- * so you need to run NANSI.SYS or equivalent.
- */
- ioctl(1,TIOCGETP,&ttybuf);
- ttybuf.sg_flags = RAW;
- ioctl(1,TIOCSETP,&ttybuf);
- # endif
- #endif
-
- #if (defined(MSC) || defined(__TURBOC__))
- orgcritvect = getvect(0x24);
- setvect(0x24,crit_hdl);
- atexit(crit_remove);
- #endif
- }
- /* Called just before exiting to restore console state */
- iostop()
- {
- #if (!defined(MSC) && !defined(__TURBOC__))
- # ifdef RAWCON
- struct sgttyb ttybuf;
- # endif
- #endif
-
- #if (!defined(MSC) && !defined(__TURBOC__))
- # ifdef RAWCON
- ioctl(1,TIOCGETP,&ttybuf);
- ttybuf.sg_flags &= ~RAW;
- ioctl(1,TIOCSETP,&ttybuf);
- # endif
- #endif
- while(ifaces != NULLIF){
- /* first flush the interface's buffers */
- while(ifaces->recv != NULLFP && (*ifaces->recv)(ifaces))
- ;
- if(ifaces->stop != NULLFP)
- (*ifaces->stop)(ifaces);
- ifaces = ifaces->next;
- }
- }
-
- /* Print or Set the date and time */
-
- dodate(argc,argv)
- int argc;
- char *argv[];
- {
- long tloc;
- register char *p;
- #ifdef MSC
- struct dosdate_t dosdate;
- struct dostime_t dostime;
- #endif
- #ifdef __TURBOC__
- struct date dosdate;
- struct time dostime;
- #endif
-
- if (argc < 2) {
- time(&tloc);
- printf("%s",ctime(&tloc));
- return 0;
- }
-
- #if (defined(MSC) || defined(__TURBOC__))
- p = argv[1];
-
- if (strlen(p) != 10 && strlen(p) != 12)
- return -1;
- while (*p)
- if (!isdigit(*p++))
- return -1;
-
- # ifdef MSC
- _dos_getdate(&dosdate); /* read the year */
- p = argv[1];
- dosdate.month = 10 * p[0] + p[1] - 11 * '0';
- dosdate.day = 10 * p[2] + p[3] - 11 * '0';
- dostime.hour = 10 * p[4] + p[5] - 11 * '0';
- dostime.minute = 10 * p[6] + p[7] - 11 * '0';
- dostime.second = 10 * p[8] + p[9] - 11 * '0';
- if (p[10]) {
- if ((dosdate.year = 10 * p[10] + p[11] - 11 * '0' + 1900) < 1980)
- dosdate.year += 100;
- }
- dostime.hsecond = 0;
-
- if (_dos_settime(&dostime) || _dos_setdate(&dosdate))
- return -1;
- # endif
- # ifdef __TURBOC__
- getdate(&dosdate); /* read the year */
- p = argv[1];
- dosdate.da_mon = 10 * p[0] + p[1] - 11 * '0';
- dosdate.da_day = 10 * p[2] + p[3] - 11 * '0';
- dostime.ti_hour = 10 * p[4] + p[5] - 11 * '0';
- dostime.ti_min = 10 * p[6] + p[7] - 11 * '0';
- dostime.ti_sec = 10 * p[8] + p[9] - 11 * '0';
- if (p[10]) {
- if ((dosdate.da_year = 10 * p[10] + p[11] - 11 * '0' + 1900) < 1980)
- dosdate.da_year += 100;
- }
- dostime.ti_hund = 0;
-
- settime(&dostime);
- setdate(&dosdate);
- # endif
- #else
- printf("Date/Time setting not supported in this version!\n");
- #endif
-
- return 0;
- }
-
- /* Spawn subshell */
- doshell(argc,argv)
- int argc;
- char *argv[];
-
- {
- char *command,**envp;
- int ret;
- #ifdef MSDOS
- unsigned short envseg;
- #endif
- #if (!defined(MSC) && !defined(__TURBOC__))
- # ifdef RAWCON
- struct sgttyb ttybuf,ttysav;
-
- ioctl(1,TIOCGETP,&ttysav);
- ioctl(1,TIOCGETP,&ttybuf);
- ttybuf.sg_flags &= ~RAW;
- ioctl(1,TIOCSETP,&ttybuf);
- # endif
- #endif
-
- if((command = getenv("COMSPEC")) == NULLCHAR)
- command = "/COMMAND.COM";
-
- #ifdef SERVERS
- if (logfp != NULLFILE) /* logging to file? */
- fclose(logfp);
- #endif
-
- #ifdef TRACE
- if (trfp != stdout) /* trace to file? */
- fclose(trfp); /* close it during shell exec */
- #endif
-
- envp = make_env(); /* create env, starts on PARA bound */
-
- #if (defined(MSC) || defined(__TURBOC__))
- ret = spawnve(P_WAIT,command,&argv[0],envp);
- #else
- if (envp != NULLCHRP) /* could the env be allocated? */
- envseg = getds() + (((unsigned) envp[0]) >> 4); /* get segment addr of env */
- else
- envseg = 0; /* no space, pass our own env */
-
- ret = fexecve(command,&argv[0],envseg);
- # ifdef RAWCON
- ioctl(1,TIOCSETP,&ttysav);
- # endif
- #endif
-
- free_env(); /* free the envp and temp env */
-
- #ifdef SERVERS
- if (logfp != NULLFILE) /* re-open logfile if it was open */
- logfp = fopen(logname,"a+");
- #endif
-
- #ifdef TRACE
- if (trfp != stdout) /* re-open tracefile if not stdout */
- if ((trfp = fopen(trname,"a+")) == NULLFILE)
- trfp = stdout;
- #endif
-
- if (ret != 0)
- return -1;
-
- #if (defined(MSC) || defined(__TURBOC__))
- return 0;
- #else
- return wait();
- #endif
- }
-
- #if (!defined(MSC) && !defined(__TURBOC__))
- /* the following piece of code was taken from the Aztec 4.10 runtime */
- /* source for fexecv() and slightly adapted to pass the environment */
- /* to the executed program. */
- /* Copyright (C) 1983, 1984 by Manx Software Systems */
-
- fexecve(path, argv, env)
- char *path, **argv;
- unsigned short env;
- {
- register char *cp, *xp;
- int i;
- char buffer[130];
- char fcb1[16], fcb2[16];
-
- cp = buffer+1;
- i = 1;
- fcbinit(".", fcb1); /* initialize fcb's, in case no args */
- fcbinit(".", fcb2);
- if (*argv) {
- ++argv; /* skip arg0, used for unix (tm) compatibility */
- while ((xp = *argv++) != '\0') {
- if (i == 1)
- fcbinit(xp, fcb1);
- else if (i == 2)
- fcbinit(xp, fcb2);
- *cp++ = ' ';
- while (*xp) {
- if (cp >= buffer+127)
- goto done;
- *cp++ = *xp++;
- }
- ++i;
- }
- }
- done:
- buffer[0] = cp - (buffer+1);
- *cp = '\r'; /* add CR to make some dos commands happy */
- return fexec(path, env, buffer, fcb1, fcb2);
- }
- #endif
-
- /* checks the time then ticks and updates ISS */
- static short clockstart = 0;
- static int32 clkval = 0;
- void
- check_time()
- {
- int32 iss();
- int32 ntime;
- int maxticks = SEC2TICK(15); /* upper limit on delayed ticks */
- char i_state;
- #if (defined(MSC) || defined(__TURBOC__))
- # define peekw(off,seg) (*((unsigned far*) (((long) (seg) << 16) | (off))))
- #else
- extern int16 peekw();
- #endif
-
- if(!clockstart){
- /* Executed only once */
- i_state = disable();
- clkval = ((int32) peekw(0x6e,0x40) << 16) | peekw(0x6c,0x40);
- restore(i_state);
- clockstart = 1;
- return;
- }
- /* set the "watchhw" bit of "watchport" (when it is defined) */
- if (watchhw)
- outportb(watchport,inportb(watchport) | watchhw);
-
- /* Read the low order word of the BIOS tick counter directly. The
- * INT 1Ah call isn't used because it stupidly clears the
- * "midnight passed" flag and we'd have to update the date ourselves.
- * (See Norton, p222).
- *
- * The PC's time-of-day handling is a real crock of shit. Why not a
- * nice simple long binary count from a fixed UTC epoch, as in UNIX??
- */
- i_state = disable();
- ntime = ((int32) peekw(0x6e,0x40) << 16) | peekw(0x6c,0x40);
- restore(i_state);
-
- /* separately check for time-of-day rollover to prevent strange
- * behaviour of the timers at midnight...
- */
- if (ntime < clkval){
- clkval -= 1573040L; /* counts per day */
- }
-
- while(ntime != clkval){ /* Handle possibility of several missed ticks */
- #ifdef IP
- icmpclk(); /* Call this one before tick */
- #endif
- tick();
- #ifdef IP
- (void)iss();
- #endif
- if(maxticks--) /* check limit on ticks to handle */
- clkval++;
- else
- clkval = ntime; /* ignore any remaining ticks */
- }
- /* clear the "watchhw" bit of "watchport" (when it is defined) */
- if (watchhw)
- outportb(watchport,inportb(watchport) & ~watchhw);
- }
- /* Read characters from the keyboard, translating them to "real" ASCII
- * If none are ready, return the -1 from kbraw()
- */
- int
- kbread()
- {
- int kbraw(),c;
-
- if((c = kbraw()) == 0){
- /* Lead-in to a special char */
- c = kbread();
- switch(c){
- case 3: /* NULL (bizzare!) */
- c = 0;
- break;
- case 59: /* F-1 key */
- c = -11;
- break;
- case 60: /* F-2 key */
- c = -10;
- break;
- case 61: /* F-3 key */
- c = -9;
- break;
- case 62: /* F-4 key */
- c = -8;
- break;
- case 63: /* F-5 key */
- c = -7;
- break;
- case 64: /* F-6 key */
- c = -6;
- break;
- case 65: /* F-7 key */
- c = -5;
- break;
- case 66: /* F-8 key */
- c = -4;
- break;
- case 67: /* F-9 key */
- c = -3;
- break;
- case 68: /* F-10 key (used as command-mode escape) */
- c = -2;
- break;
- case 71: /* HOME key */
- c = -20;
- break;
- case 72: /* UP arrow */
- c = -19;
- break;
- case 73: /* PAGE UP */
- c = -18;
- break;
- case 75: /* LEFT arrow */
- c = -17;
- break;
- case 77: /* RIGHT arrow */
- c = -16;
- break;
- case 79: /* END key */
- c = -15;
- break;
- case 80: /* DOWN arrow */
- c = -14;
- break;
- case 81: /* PAGE DOWN */
- c = -13;
- break;
- case 82: /* INS key */
- c = -12;
- break;
- case 83: /* DEL key */
- c = 0x7f;
- break;
- default: /* Dunno what it is */
- c = -1;
- }
- }
- return c;
- }
-
- #if (!defined(MSC) && !defined(__TURBOC__))
- #define CTLZ 26
- /* Special version of aputc() (used by putchar and printf) that filters
- * out nasty characters that screw up the DDOS and ANSI terminal drivers
- * Also, it facilitates re-routing of standard output to an alternative
- * handler, e.g. to send it via TCP.
- */
- int (*put_stdout)() = (int (*)()) 0;
- int
- aputc(c,file)
- int c;
- FILE *file;
- {
- if(file == stdout){
- /* Nulls get displayed as spaces by ansi.sys (wrong)
- * ^Z's seem to hang the DoubleDos and DesqView screen drivers
- */
- if((c == '\0' || c == CTLZ))
- return c;
-
- /* Check for presence of alternative putc function
- */
- if(put_stdout != (int (*)()) 0)
- return (*put_stdout)(c,file);
- }
- /* Do end-of-line translations */
- if(c == '\n')
- putc('\r',file);
- return putc(c,file);
- }
- #endif
-
- /* Reset the CPU, reboot DOS */
- sysreset()
- {
- void (*reset)(); /* just a pointer to function */
-
- reset = (void (*)()) 0xffff0000; /* point to reset location */
- (*reset)(); /* and call it */
- }
-
- #if (!defined(LARGEDATA))
- /* Convert a pointer to a long integer, so that it can be printed in a
- compiler- and system-independent way.
- This function currently assumes that pointers are 16-bit (int) size.
- */
- long ptr2long (p)
- char *p;
- {
- unsigned int rv = (unsigned int) p;
-
- return (long) rv;
- }
- #endif
-
- #ifdef __TURBOC__
- /* the strrchr() function is broken in Turbo C 2.0 */
- /* this implementation is probably more efficient, too... */
-
- char *strrchr (const char *s, int c)
-
- {
- register char *rv = NULL; /* return value */
-
- do
- {
- if (*s == (char) c) /* a match here? */
- rv = (char *) s; /* remember it */
- }
- while (*s++);
-
- return rv; /* return last match or NULL */
- }
- #endif
-
- #ifdef MSC
- int memstat (argc,argv)
- int argc;
- char *argv[];
-
- {
- #ifdef SHOWHEAP
- unsigned long used;
- struct heapinfo {
- int far *pentry;
- size_t size;
- int useflag;
- } hinfo;
- #endif
- int _heapset();
- #ifndef LARGEDATA
- unsigned int _memavl(),_memmax();
- #endif
-
- #ifdef SHOWHEAP
- if (argc > 1){
- used = 0;
- hinfo.pentry = NULL;
- while (_heapwalk(&hinfo) == _HEAPOK) {
- switch (hinfo.useflag)
- {
- case _FREEENTRY:
- printf("%8u",hinfo.size);
- break;
- case _USEDENTRY:
- used += hinfo.size;
- break;
- }
- }
- printf("\n%lu bytes used, ",used);
- }
- #endif
-
- #ifdef LARGEDATA
- printf("heap %s\n",(_heapset(0) == _HEAPOK)? "okay":"BAD");
- #else
- printf("%u bytes available, largest block %u bytes, heap %s\n",
- _memavl(),_memmax(),(_heapset(0) == _HEAPOK)? "okay":"BAD");
- #endif
-
- return 0;
- }
- #endif
-
- /* control the watchdog function */
-
- int
- dowatchdog (argc,argv)
- int argc;
- char *argv[];
- {
- switch (argc)
- {
- case 3:
- watchhw = htoi(argv[2]) & 0xff;
- case 2:
- if ((watchport = htoi(argv[1])) == 0) {
- printf("Usage: %s [<port> <value>]\n",argv[0]);
- watchhw = 0;
- }
- break;
- case 1:
- if (watchhw)
- printf("PORT=%04x VALUE=%02x\n",watchport,watchhw);
- else
- printf("OFF\n");
- break;
- }
- return 0;
- }
-